<?php // $Id: sharpobj_processor.php,v 1.5 2006/07/04 13:34:55 alex Exp $
// 

/**
 * Процессор - обработчик данных
 * Управляет преобразованиями данных в справочниках в соответствии с бизнес-логикой
 * Методы, доступные через action(), должны иметь префикс act_,
 * принимать в качестве параметра sharpobj_data_item или NULL
 * и возвращать sharpobj_data_item, NULL или один из преобразуемых типов
 * (сейчас это только Int)
 * Допускается создавать методы для внутренного пользования, с префиксом pvt_
 * ограничений по принимаемым и возвращаемым значениям на них не накладывается
 *
 */
abstract class sharpobj_processor
{
    // Управление справочниками
    protected $storages = array();
    function storageAdd($name,$storage)
    {
        $this->storages[$name] = $storage;
    }
    function storageObj($name,$dapapath=null)
    {
        return $this->storageLink($name)->getObj($dapapath);
    }
    /**
     * Ссылка на справочники
     *
     * @param string $name
     * @return 
     */
    protected function storageLink($name)
    {
        if (!isset($this->storages[$name]))
        {
            mst_error('Хранилище не существует',"Хранилище с кодом ({$name})  в процессоре ".get_class($this)." отсутствует",1);
            return false;
        }
        return $this->storages[$name];
    }
    /**
     * Запрос к процессору, совместимый с запросом через порт
     * (для совместимости интерфейсов)
     * @param string $class - игнорируется
     * @param string $func - имя функции
     * @param string $dataobj - объект с данными
     * @param string $portname - игнорируется
     * @return 
     */
    function query($func,$dataobj=null,$class='main',$portname=null)
    {
        // Исполнить запрос
        $result = $this->action($func,$dataobj);;
		// Проверяем результат на ошибку
		if (sharpobj_iserror($result))
		{
			// Возвращено сообщение об ошибке
			mst_error('Ошибка запроса','При запросе к sharpobj_processor'
					.' произошла ошибка "'.$result->get('plain','name').'" '
					.' ('.$result->get('plain','about').')',1);
			return false;
		}
		return $result;
        
    }
    /**
     * Исполнить запрос
     *
     * @param string $func
     * @param sharpobj_data_interface_item $dataobj
     * @return sharpobj_data_interface_item
     */
    function action($func,$dataobj=null)
    {
        // Исполнить запрос

		// Проверяем соответствия аргумента

        if(is_null($dataobj)
        OR ($dataobj instanceof sharpobj_data_interface_item))
        {
            // Объект в перекодировке не нуждается
        }elseif (is_int($dataobj))
        {
            // Конвертируем в объект
            $dataobj = sharpobj_conv_int_obj($dataobj);
        }elseif(is_array($dataobj))
        {
            // Нам передали массив
            $dataobj = sharpobj_conv_array_obj($dataobj);
        }elseif(is_string($dataobj))
        {
            // Нам передали массив
            $dataobj = sharpobj_conv_string_obj($dataobj);
        }else
        {
            // var_dump($dataobj);
            return sharpobj_error('type','Неправильное значение'
            ,"Метод ({$func}) класса ".get_class($this)." должен получать объект, int, null или array",3);
        }


		// Выполняем запрос
    	// Определяем имя метода
		$dsr = 'sc_';
		// Длинна строки
		$dsr_len =strlen($dsr);
		if(substr($func,0,$dsr_len) === $dsr)
		{
			// Здесь мы выбираем разрешенный тип стандартного действия 
			// можно было бы сделать красивее... когда-нибудь потом 
			if (substr($func,$dsr_len,$do_len= strlen($do_name='get_')) === $do_name)
			{
				
			}elseif (substr($func,$dsr_len,$do_len= strlen($do_name='getObj_')) === $do_name)
			{
				//
			}elseif (substr($func,$dsr_len,$do_len= strlen($do_name='insert_')) === $do_name)
			{
				//
			}elseif (substr($func,$dsr_len,$do_len= strlen($do_name='update_')) === $do_name)
			{
				//
			}elseif (substr($func,$dsr_len,$do_len= strlen($do_name='delete_')) === $do_name)
			{
				//
			}elseif (substr($func,$dsr_len,$do_len= strlen($do_name='count_')) === $do_name)
			{
				//
			}elseif (substr($func,$dsr_len,$do_len= strlen($do_name='getListAll_')) === $do_name)
			{
				//
			}elseif (substr($func,$dsr_len,$do_len= strlen($do_name='sqlAction_')) === $do_name)
			{
				//
			}else
			{
				// Ошибка
				return sharpobj_error('action','Действие не определено'
							,"Метод ({$func}) класса ".get_class($this)." не определен",3);
			}
			$stname = substr($func,$dsr_len+$do_len);
			$func = substr($func,0,$dsr_len+$do_len-1);
			$result = $this->$func($dataobj,$stname);
		}else
		{
			// 
        	$func = 'act_'.$func;
        	if (!method_exists($this,$func))
        	{
        	    return sharpobj_error('action','Неправильный вызов'
           			 ,"Метод ({$func}) класса ".get_class($this)." не существует",3);
        	}
        	$result = $this->$func($dataobj);
		}
		// !Надо бы сделать проверку существования метода

        
        
		// Проверяем соответствие результата
		if (!($result instanceof sharpobj_data_interface_item) AND !is_null($result))
		{
			//
			if (is_int($result))
			{
				// Число возвращаем в неизменном виде
				$result =  $result; //  sharpobj_conv_int_obj($result);
			}elseif(is_null($result) OR is_bool($result))
			{
				return $result;
			}elseif(is_string($dataobj))
            {
            	// Нам передали строку
                return $result;
            }elseif(is_array($result))
            {
            	// Нам передали массив
                $result = sharpobj_conv_array_obj($result);
            }else
			{
				// var_dump($dataobj);
				return sharpobj_error('type','Неправильное значение'
							,"Метод ({$func}) класса ".get_class($this)." вернул значение недопустимого типа "
							        .gettype($result)."=".print_r($result,true),3);
			}	
		}elseif ($result instanceof sharpobj_data_item_int)
		{
			$result = $result->getP();
		}elseif ($result instanceof sharpobj_data_item_string)
		{
			$dataobj = sharpobj_conv_obj_string($dataobj);
		}
		return $result;    
    }

	// ******************
	// Стандартные вызовы
	
    /**
     * Вернуть пустой объект хранилища
     */
	protected function sc_getObj($dataobj=null,$stname)
	{
		return $this->storageLink($stname)->getObj();
	}
	
	/**
	 * Возвращаем объект по id
	 */
	protected function sc_get($dataobj,$stname)
	{
		return $this->storageLink($stname)->get($dataobj);
	}
	
	/**
	 * Вставляем объект в базу
	 */
	protected function sc_insert($dataobj,$stname)
	{
		return $this->storageLink($stname)->insert($dataobj);
	}
	
	/**
	 * Обновляем объект в базе
	 */
	protected function sc_update($dataobj,$stname)
	{
		return $this->storageLink($stname)->update($dataobj);
	}
	
	/**
	 * Удаляем объект из базы
	 */
	protected function sc_delete($dataobj,$stname)
	{
		return $this->storageLink($stname)->delete($dataobj);
	}
	
	/**
	 * Считаем объекты в базе
	 */
	protected function sc_count($dataobj=null,$stname)
	{
		return $this->storageLink($stname)->count();
	}	
	/**
	 * Получаем список объектов из базы
	 */
	protected function sc_getListAll($dataobj,$stname)
	{
		$from = null; $limit = null;
		if ($dataobj instanceof sharpobj_data_item_data)
		{
			$from = $dataobj->get('sql','from');
			$limit = $dataobj->get('sql','limit');
		}
		return $this->storageLink($stname)->getListAll($from,$limit);	
	}
	
	/**
	 * Выполняем действие в базе данных (только для sql хранилищ)
	 */
	protected function sc_sqlAction($dataobj=null,$stname)
	{
		return $this->storageLink($stname)->sqlqueryAction($dataobj->getP());
	}
	// ******************
	// Утилиты
	/**
	 * Проверка соединения	
	 * @param $o
	 * @return unknown
	 */
	protected function act_tls_lo($o)
	{
		return $o;
	}

}

/*
 * Контейнер для информации об ограничениях списка в getListAll
 */
class sharpobj_data_item_listlimit extends sharpobj_data_item_data 
{
	//
    function __construct($limit=null,$from=null)
    {
    	$options=null;
        parent::__construct($options);
        $this->addItem('from','int');
        $this->addItem('limit','int');
        $this->set('plain',$limit,'limit');
		$this->set('plain',$from,'from');
    }
}

?>